/*********************************************************************************************************************
* MM32F327X-G9P Opensourec Library 即（MM32F327X-G9P 开源库）是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
* 
* 本文件是 MM32F327X-G9P 开源库的一部分
* 
* MM32F327X-G9P 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPL（GNU General Public License，即 GNU通用公共许可证）的条款
* 即 GPL 的第3版（即 GPL3.0）或（您选择的）任何后来的版本，重新发布和/或修改它
* 
* 本开源库的发布是希望它能发挥作用，但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
* 
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有，请参阅<https://www.gnu.org/licenses/>
* 
* 额外注明：
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明（即本声明）
* 
* 文件名称          main
* 公司名称          成都逐飞科技有限公司
* 版本信息          查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境          IAR 8.32.4 or MDK 5.37
* 适用平台          MM32F327X_G9P
* 店铺链接          https://seekfree.taobao.com/
* 
* 修改记录
* 日期              作者                备注
* 2022-08-10        Teternal            first version
********************************************************************************************************************/

#include "zf_common_headfile.h"

// 打开新的工程或者工程移动了位置务必执行以下操作
// 第一步 关闭上面所有打开的文件
// 第二步 project->clean  等待下方进度条走完


// *************************** 例程硬件连接说明 ***************************
// 核心板正常供电即可 无需额外连接


// *************************** 例程测试说明 ***************************
// 1.核心板烧录完成本例程，完成上电
// 
// 2.可以看到核心板上 B13 LED 闪烁
// 
// 3.将 KEY1 宏定义对应的引脚 按一次主板按键或者从悬空状态接到 GND 然后再断开 可以看到 H2 LED 闪烁一次
// 
// 4.将 KEY2 宏定义对应的引脚 按一次主板按键或者从悬空状态接到 GND 可以看到 H2 LED 闪烁两次 然后再断开
// 
// 5.将 KEY3 宏定义对应的引脚 按一次主板按键或者从悬空状态接到 GND 可以看到 H2 LED 闪烁三次 然后再断开 可以看到 H2 LED 闪烁三次
// 
// 6.将 KEY4 宏定义对应的引脚 按一次主板按键或者从悬空状态接到 GND 可以看到 H2 LED 闪烁四次 然后再断开 可以看到 H2 LED 闪烁四次
// 
// 如果发现现象与说明严重不符 请参照本文件最下方 例程常见问题说明 进行排查


// **************************** 代码区域 ****************************
#define LED1                    (H2 )
#define LED2                    (B13)

#define KEY1                    (G0 )                                           // 使用的外部中断输入引脚 如果修改 需要同步对应修改外部中断编号与 isr.c 中的调用
#define KEY2                    (G1 )                                           // 使用的外部中断输入引脚 如果修改 需要同步对应修改外部中断编号与 isr.c 中的调用
#define KEY3                    (G2 )                                           // 使用的外部中断输入引脚 如果修改 需要同步对应修改外部中断编号与 isr.c 中的调用
#define KEY4                    (G3 )                                           // 使用的外部中断输入引脚 如果修改 需要同步对应修改外部中断编号与 isr.c 中的调用

#define KEY1_EXTI               (EXTI0_IRQn)                                    // 对应外部中断的中断编号 在 mm32f3277gx.h 头文件中查看 IRQn_Type 枚举体
#define KEY2_EXTI               (EXTI1_IRQn)                                    // 对应外部中断的中断编号 在 mm32f3277gx.h 头文件中查看 IRQn_Type 枚举体
#define KEY3_EXTI               (EXTI2_IRQn)                                    // 对应外部中断的中断编号 在 mm32f3277gx.h 头文件中查看 IRQn_Type 枚举体
#define KEY4_EXTI               (EXTI3_IRQn)                                    // 对应外部中断的中断编号 在 mm32f3277gx.h 头文件中查看 IRQn_Type 枚举体

uint8 exti_state[4];

int main (void)
{
    clock_init(SYSTEM_CLOCK_120M);                                              // 初始化芯片时钟 工作频率为 120MHz
    debug_init();                                                               // 初始化默认 Debug UART

    // 此处编写用户代码 例如外设初始化代码等
    uint16 loop_time = 0;

    gpio_init(LED1, GPO, GPIO_HIGH, GPO_PUSH_PULL);                             // 初始化 LED1 输出 默认高电平 推挽输出模式
    gpio_init(LED2, GPO, GPIO_HIGH, GPO_PUSH_PULL);                             // 初始化 LED2 输出 默认高电平 推挽输出模式

    exti_init(KEY1, EXTI_TRIGGER_RISING);                                       // 初始化 KEY1 为外部中断输入 上升沿触发
    exti_init(KEY2, EXTI_TRIGGER_FALLING);                                      // 初始化 KEY2 为外部中断输入 下降沿触发
    exti_init(KEY3, EXTI_TRIGGER_BOTH);                                         // 初始化 KEY3 为外部中断输入 双边沿触发
    exti_init(KEY4, EXTI_TRIGGER_BOTH);                                         // 初始化 KEY4 为外部中断输入 双边沿触发

    interrupt_set_priority(KEY1_EXTI, 0);                                       // 设置 KEY1 对应外部中断的中断有先级为 0
    interrupt_set_priority(KEY2_EXTI, 1);                                       // 设置 KEY2 对应外部中断的中断有先级为 1
    interrupt_set_priority(KEY3_EXTI, 2);                                       // 设置 KEY3 对应外部中断的中断有先级为 2
    interrupt_set_priority(KEY4_EXTI, 3);                                       // 设置 KEY4 对应外部中断的中断有先级为 3
    // 此处编写用户代码 例如外设初始化代码等

    while(1)
    {
        // 此处编写需要循环执行的代码
        if(exti_state[0])
        {
            for(loop_time = 1; loop_time > 0; loop_time --)
            {
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
            }
            exti_state[0] = 0;                                                  // 清空外部中断触发标志位
        }
        else if(exti_state[1])
        {
            for(loop_time = 2; loop_time > 0; loop_time --)
            {
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
            }
            exti_state[1] = 0;                                                  // 清空外部中断触发标志位
        }
        else if(exti_state[2])
        {
            for(loop_time = 3; loop_time > 0; loop_time --)
            {
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
            }
            exti_state[2] = 0;                                                  // 清空外部中断触发标志位
        }
        else if(exti_state[3])
        {
            for(loop_time = 4; loop_time > 0; loop_time --)
            {
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
                gpio_toggle_level(LED1);                                        // 翻转 LED 引脚输出电平 控制 LED 亮灭
                system_delay_ms(100);                                           // 延时
            }
            exti_state[3] = 0;                                                  // 清空外部中断触发标志位
        }
        else
        {
            gpio_toggle_level(LED2);                                            // 翻转 LED 引脚输出电平 控制 LED 亮灭
            system_delay_ms(200);                                               // 延时
        }
        // 此处编写需要循环执行的代码
    }
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     KEY1 的按键外部中断处理函数 这个函数将在 KEY1 引脚对应的外部中断调用 详见 isr.c
// 参数说明     void
// 返回参数     void
// 使用示例     key1_exti_handler();
//-------------------------------------------------------------------------------------------------------------------
void key1_exti_handler (void)
{
    exti_state[0] = 1;                                                          // 外部中断触发 标志位置位
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     KEY2 的按键外部中断处理函数 这个函数将在 KEY2 引脚对应的外部中断调用 详见 isr.c
// 参数说明     void
// 返回参数     void
// 使用示例     key2_exti_handler();
//-------------------------------------------------------------------------------------------------------------------
void key2_exti_handler (void)
{
    exti_state[1] = 1;                                                          // 外部中断触发 标志位置位
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     KEY3 的按键外部中断处理函数 这个函数将在 KEY3 引脚对应的外部中断调用 详见 isr.c
// 参数说明     void
// 返回参数     void
// 使用示例     key3_exti_handler();
//-------------------------------------------------------------------------------------------------------------------
void key3_exti_handler (void)
{
    exti_state[2] = 1;                                                          // 外部中断触发 标志位置位
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     KEY4 的按键外部中断处理函数 这个函数将在 KEY4 引脚对应的外部中断调用 详见 isr.c
// 参数说明     void
// 返回参数     void
// 使用示例     key4_exti_handler();
//-------------------------------------------------------------------------------------------------------------------
void key4_exti_handler (void)
{
    exti_state[3] = 1;                                                          // 外部中断触发 标志位置位
}
// **************************** 代码区域 ****************************

// *************************** 例程常见问题说明 ***************************
// 遇到问题时请按照以下问题检查列表检查
// 
// 问题1：LED 不闪烁
//      查看程序是否正常烧录，是否下载报错，确认正常按下复位按键
//      万用表测量对应 LED 引脚电压是否变化，如果不变化证明程序未运行，如果变化证明 LED 灯珠损坏
// 
// 问题2：KEY1/KEY2/KEY3/KEY4 对应引脚接信号无 H2 LED 闪烁
//      如果使用主板测试，主板必须要用电池供电
//      查看程序是否正常烧录，是否下载报错，确认正常按下复位按键
//      万用表测量对应 LED 引脚电压是否变化，如果不变化证明程序未运行，如果变化证明 LED 灯珠损坏
//      万用表检查对应 KEY1/KEY2/KEY3/KEY4 引脚电压是否正常变化，是否跟接入信号不符，引脚是否接错
